#pragma once

#include "boolean_operation.h"
#include "../../layout/layout.hpp"
#include "../../select/select_cmd.hpp"
#include "../../utils/kutils.h"
#include "qlib/geo/polygon.h"
#include "qlib/tools/clipper_tools.h"
namespace qbe::editing::BooleanOperation {

void exit(ecs::Query query, state::AllModeType enter_mode) {
  int a = 0;
}
void init(entt::registry& reg, ecs::Commands commands, ecs::Query query) {}

// 帧开始校验
void stateTransformBegin(ecs::Query query, input::HandleBundle* handle, BooleanOperationModel& model) {
  auto& state = query.get_resource<state::State>();
  // 按下ecs必然回退
  if (handle->keyReleased(vsg::KEY_Escape)) {
    model.is_open_ui = false;
    state.exit();
    return;
  }
}

void update(entt::registry& ecs_reg, ecs::Query query, ecs::Bus& bus, ecs::EventWriter<msg::RenderEvent> event) {
  auto& state = query.get_resource<state::State>();

  // 仅在模式执行
  if (state.getEditingMode() != state::EditingModeType::Boolean)
    return;

  //获取当前操作的Cell
  auto& cmd = query.get_resource<layout::CellCmd>();

  auto cell = cmd.get_cell();
  auto& reg = cell->reg;
  auto& cell_state = query.get_resource<layout::CellState>();

  //获取选择对象
  std::vector<entt::entity> select_arr;
  for (auto [e] : reg.view<select::SelectTag>().each()) {
    select_arr.push_back(e);
  }

  if (select_arr.empty()) {
    state.exit();
    return;
  }
  auto& layer_interface = query.get_resource<tools::LayerInterfaceObjcet>();

  auto& model = query.get_resource<BooleanOperationModel>();
  model.m_operate_select_arr.clear();
  model.cell = cell;
  model.layer_interface = layer_interface;

  auto& handModule = query.get_resource<vsg::ref_ptr<input::HandleBundle>>();
  stateTransformBegin(query, handModule, model);

  if (state.getEditingMode() != state::EditingModeType::Boolean)
    return;

  std::vector<std::pair<entt::entity, qlib::PolygonPtrArray>>& operate_select_arr = model.m_operate_select_arr;
  std::unordered_set<uint32_t>& select_layer_set = model.m_select_layer_set;
  for (auto [e] : reg.view<select::SelectTag>().each()) {
    auto ellipse_ptr = reg.try_get<qlib::Ellipse::s_ptr>(e);
    if (ellipse_ptr) {
      qlib::Polygon::s_ptr pol = (*ellipse_ptr)->to_polygon();
      operate_select_arr.push_back(std::make_pair(e, qlib::PolygonPtrArray{pol}));
      select_layer_set.insert((*ellipse_ptr)->layer);
    }

    auto rectangle_ptr = reg.try_get<qlib::Rectangle::s_ptr>(e);
    if (rectangle_ptr) {
      qlib::Polygon::s_ptr pol = (*rectangle_ptr)->to_polygon();
      operate_select_arr.push_back(std::make_pair(e, qlib::PolygonPtrArray{pol}));
      select_layer_set.insert((*rectangle_ptr)->layer);
    }

    auto polygon_ptr = reg.try_get<qlib::Polygon::s_ptr>(e);
    if (polygon_ptr) {
      operate_select_arr.push_back(std::make_pair(e, qlib::PolygonPtrArray{(*polygon_ptr)}));
      select_layer_set.insert((*polygon_ptr)->layer);
    }

    auto fan_ptr = reg.try_get<qlib::Fan::s_ptr>(e);
    if (fan_ptr) {
      qlib::Polygon::s_ptr pol = (*fan_ptr)->to_polygon();
      operate_select_arr.push_back(std::make_pair(e, qlib::PolygonPtrArray{pol}));
      select_layer_set.insert((*fan_ptr)->layer);
    }

    auto path_ptr = reg.try_get<qlib::Path::s_ptr>(e);
    if (path_ptr && (*path_ptr)->width != 0.0) {
      qlib::PolygonPtrArray pols;
      (*path_ptr)->to_polygons(false, qlib::Tag{0, 0}, pols);
      operate_select_arr.push_back(std::make_pair(e, pols));
      select_layer_set.insert((*path_ptr)->layer);
    }
  }

  if (model.is_open_ui == false) {
    bus.send(qbe::UiMessage::BooleanOperation_Open());
    model.is_open_ui = true;
  }

  auto res_method_change = bus.receive<qbe::UiMessage::BooleanOperation_MethodIndexChanged>();
  if (!res_method_change.empty()) {
    qbe::UiMessage::BooleanOperation_MethodIndexChanged method_change =
        std::any_cast<qbe::UiMessage::BooleanOperation_MethodIndexChanged>(res_method_change[0]);
    model.m_ok_enable = true;
    qbe::UiMessage::BooleanOperation_ObjectState dialog_object_info;
    if (method_change.method_text == "OR" || method_change.method_text == "NOT") {
      dialog_object_info.show_operation_object = false;
      if (operate_select_arr.size() == 2) {
        model.m_element_a = operate_select_arr[0];
        model.m_element_b = operate_select_arr[1];
      }
    } else {
      dialog_object_info.show_operation_object = true;

      std::string info = getOperationObjectInfo(method_change.method_text, model);  //里面会修改确认按钮置灰标志位
      dialog_object_info.operation_object_info = QString::fromStdString(info);
    }
    dialog_object_info.ok_enable = model.m_ok_enable;
    bus.send(dialog_object_info);
  }

  auto res_ok = bus.receive<qbe::UiMessage::BooleanOperation_Ok>();
  if (!res_ok.empty()) {
    qbe::UiMessage::BooleanOperation_Ok ok_msg = std::any_cast<qbe::UiMessage::BooleanOperation_Ok>(res_ok[0]);
    onOk(query, model, ok_msg);
    if (model.is_open_ui == true) {
      bus.send(qbe::UiMessage::BooleanOperation_Close());
      model.is_open_ui = false;
    }
  }

  auto res_close = bus.receive<qbe::UiMessage::BooleanOperation_Close>();
  if (!res_close.empty()) {
    //state.switchMode(state::EditingModeType::None);
    state.exit();
    model.is_open_ui = false;
  }
}

void post(entt::registry& reg, ecs::Commands commands, ecs::Query query, ecs::Bus& bus) {}

void onOk(ecs::Query query, BooleanOperationModel& model, qbe::UiMessage::BooleanOperation_Ok& ok_msg) {
  auto& state = query.get_resource<state::State>();
  auto& undoRedoModule = query.get_resource<undoRedoT::UndoRedoModule>();
  auto& layout_cmd = query.get_resource<layout::LayoutCmd>();
  auto& select_cmd = query.get_resource<select::SelectCmd>();
  state.exit();

  qlib::PolygonPtrArray gdspolygon_list_a;
  qlib::PolygonPtrArray gdspolygon_list_b;

  if (model.m_operate_select_arr.size() == 2) {
    gdspolygon_list_a = model.m_element_a.second;
    gdspolygon_list_b = model.m_element_b.second;
  }

  if (model.m_operate_select_arr.size() > 2) {
    if (model.m_select_layer_set.size() == 2) {
      std::vector<uint32_t> layer_vec;
      for (auto& it : model.m_select_layer_set) {
        layer_vec.push_back(it);
      }
      uint32_t layer_a = layer_vec[0];
      uint32_t layer_b = layer_vec[1];

      if (layer_a > layer_b) {
        uint32_t temp_layer = layer_a;
        layer_a = layer_b;
        layer_b = temp_layer;
      }

      for (int i = 0; i < model.m_operate_select_arr.size(); i++) {
        qlib::Polygon::s_ptr polygon = model.m_operate_select_arr[i].second[0];
        if (polygon->layer == layer_a) {
          gdspolygon_list_a = model.m_operate_select_arr[i].second;
        }
        if (polygon->layer == layer_b) {
          gdspolygon_list_b = model.m_operate_select_arr[i].second;
        }
      }
    }
    if (model.m_operate_select_arr.size() != 2) {
      qlib::Polygon::s_ptr first_polygon = model.m_operate_select_arr[0].second[0];
      gdspolygon_list_a.push_back(first_polygon);

      for (int i = 1; i < model.m_operate_select_arr.size(); i++) {
        qlib::PolygonPtrArray other_polygon = model.m_operate_select_arr[i].second;
        gdspolygon_list_b.insert(gdspolygon_list_b.end(), other_polygon.begin(), other_polygon.end());
      }
    }
  }

  qlib::PolygonPtrArray result;
  std::string opera_text = ok_msg.operation_method;

  if (opera_text == "OR") {
    qlib::ClipperTool::boolean(gdspolygon_list_a, gdspolygon_list_b, qlib::Operation::Or, 100, result);
  } else if (opera_text == "NOT") {
    std::vector<entt::entity> select_entitys;
    for (auto pair : model.m_operate_select_arr) {
      select_entitys.push_back(pair.first);
    }

    //计算包围盒子矩形
    auto graphs = qbe::auxiliary::getGraph(model.cell, select_entitys);
    std::vector<qlib::Vec2d> max_box = qbe::auxiliary::calBonndingBox(graphs);
    qlib::Vec2d min(max_box[0].x, max_box[0].y);
    qlib::Vec2d max(max_box[1].x, max_box[1].y);

    qlib::Rectangle::s_ptr rectangle = qlib::Rectangle::create();
    rectangle->width = max.x - min.x;
    rectangle->height = max.y - min.y;
    rectangle->pos = min;

    qlib::Polygon::s_ptr box_polygon = rectangle->to_polygon();
    qlib::PolygonPtrArray box_polygon_list = {box_polygon};

    qlib::PolygonPtrArray or_result;
    qlib::ClipperTool::boolean(gdspolygon_list_a, gdspolygon_list_b, qlib::Operation::Or, 10e7, or_result);
    qlib::ClipperTool::boolean(box_polygon_list, or_result, qlib::Operation::Not, 10e7, result);
  } else if (opera_text == "AND") {
    qlib::ClipperTool::boolean(gdspolygon_list_a, gdspolygon_list_b, qlib::Operation::And, 10e7, result);
  } else if (opera_text == "XOR") {
    qlib::ClipperTool::boolean(gdspolygon_list_a, gdspolygon_list_b, qlib::Operation::Xor, 10e7, result);
  } else if (opera_text == "A-B") {
    qlib::ClipperTool::boolean(gdspolygon_list_a, gdspolygon_list_b, qlib::Operation::Not, 10e7, result);

  } else if (opera_text == "B-A") {
    qlib::ClipperTool::boolean(gdspolygon_list_b, gdspolygon_list_a, qlib::Operation::Not, 10e7, result);
  }

  undoRedoModule.start(model.cell);

  std::vector<entt::entity> result_entitys;
  for (auto polygon_ptr : result) {
    entt::entity entity = model.cell->reg.create();
    model.cell->reg.emplace<qlib::Polygon::s_ptr>(entity, polygon_ptr);  // 绑定指针到实体
    layout_cmd.add(entity);
    undoRedoModule.add(entity);
    result_entitys.push_back(entity);
  }

  if (ok_msg.original_layer_retention == false) {
    for (auto e : model.m_operate_select_arr) {
      undoRedoModule.dele(e.first);
      layout_cmd.remove(e.first);
    }
  }
  undoRedoModule.end();

  // 取消所有高亮
  select_cmd.clear_all();

  // 选中生成的图形
  select_cmd.add_selects(result_entitys);
  auto& sele_event_writer = query.get_event_writer<select::Event>();
  sele_event_writer.send({select::Code::SelectUpdate});
  sele_event_writer.send({select::Code::HoverUpdate});
}
}  // namespace qbe::editing::BooleanOperation
